Frontend Forever App
We have a mobile app for you to download and use. And you can unlock many features in the app.
Get it now
Intall Later
Run
HTML
CSS
Javascript
Output
Document
@charset "UTF-8"; @import url(https://fonts.googleapis.com/css?family=Nunito+Sans:300,400,600,700,800); *, :after, :before { box-sizing: border-box; padding: 0; margin: 0; } html { height: 100%; } body { margin: 0; height: 100%; display: flex; justify-content: center; align-items: center; background-color: #111; } canvas { background-color: #020703; }
console.log("Event Fired") import { Scene, Color, Container, Image, Position, NetworkEvent, Math as M } from "https://unpkg.com/pencil.js/dist/pencil.esm.js"; const { map, random } = M; const { floor, min } = Math; const baseColor = new Color("#020703"); const topColor = new Color("#92935A"); const maxTries = 100; const minRadius = 25; const maxRadius = 60; const minTreeHeight = 5; const maxTreeHeight = 10; const moveSpeed = 1; const canvas = document.createElement("canvas"); const mult = 75; canvas.width = 16 * mult; canvas.height = 9 * mult; document.body.appendChild(canvas); const scene = new Scene(canvas); const { width, height } = scene; const bottomCenter = new Position(width / 2, height); const image = new Image(undefined, "https://i.ibb.co/7gNrVLr/leaf.png"); class Tree extends Container { constructor(position, radius, stacks) { super(position); this.radius = radius; for (let i = 0; i < stacks; ++i) { this.add( new Image(undefined, image, { scale: map(i, 0, stacks, (radius / image.width) * 2, 0), tint: baseColor.clone().lerp(topColor, (i + 1) / stacks), origin: Image.origins.center, rotation: random() }) ); } } move() { this.children.forEach((stage, index) => { stage.position.set( 30 * index * (this.position.x / width - 0.5), 10 * index * (this.position.y / height - 1) ); }); } } function addTree(newPosition, trees) { const canGrow = min( ...trees.map( ({ position, radius }) => newPosition.distance(position) - radius + 10 ), // newPosition.x, newPosition.y + minRadius, height - newPosition.y + maxRadius, maxRadius ); if (canGrow > minRadius) { return new Tree( newPosition, canGrow, floor(random(minTreeHeight, maxTreeHeight)) ); } return null; } image.on(NetworkEvent.events.ready, () => { const trees = []; let fail = 0; while (fail < maxTries) { const tree = addTree(scene.getRandomPosition(), trees); if (tree) { trees.push(tree); fail = 0; } else { fail++; } } scene.add(...trees); }); scene .startLoop() .on(Scene.events.draw, () => { scene.children.forEach((tree) => { if (tree.position.x - tree.radius > width) { tree.delete(); } else { tree.position.add(moveSpeed, 0); tree.move(); tree.options.zIndex = -tree.position.distance(bottomCenter); } }); const tree = addTree( new Position(-maxRadius, random(height)), scene.children ); if (tree) { scene.add(tree); } }, true );